package com.xinziruo.crawl.infrastruture.support.command.impl;

import static com.xinziruo.crawl.infrastruture.support.command.CommandConstant.*;

import org.apache.mina.core.buffer.IoBuffer;

import com.xinziruo.crawl.infrastruture.support.command.Command;
import com.xinziruo.crawl.infrastruture.support.command.CommandConverter;
import com.xinziruo.crawl.infrastruture.support.command.CommandFactory;

/**
 * 
 * @author loudyn
 * 
 */
public class IoBufferCommandConverter implements CommandConverter<IoBuffer> {

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.youboy.client.command.CommandConverter#toCommand(java.lang.Object)
	 */
	public Command toCommand(IoBuffer buf) throws Exception {

		// ([length]:4)([contentType]:1)([content]:n)
		byte[] content = readContent(buf);
		byte contentType = getCommandContentType(content);
		byte[] commandContent = getCommandContent(content);

		Command comm = CommandFactory.newCommand(contentType);
		return comm.content(commandContent);
	}

	private byte[] readContent(IoBuffer buf) {

		int length = buf.getInt();
		byte[] content = new byte[length];
		buf.get(content);

		return content;
	}

	private byte getCommandContentType(byte[] content) {

		if (content.length < CONTENT_TYPE_BYTES) {
			throw new IllegalArgumentException("can't parse command contentType!");
		}

		int contentTypeOffset = CONTENT_TYPE_BYTES - 1;
		return content[contentTypeOffset];
	}

	private byte[] getCommandContent(byte[] content) {

		int contentLength = content.length - CONTENT_TYPE_BYTES;
		byte[] actualContent = new byte[contentLength];

		System.arraycopy(content, CONTENT_TYPE_BYTES, actualContent, 0, contentLength);
		return actualContent;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.youboy.client.command.CommandConverter#fromCommand(com.youboy.client.command.Command)
	 */
	public IoBuffer fromCommand(Command comm) throws Exception {

		IoBuffer buf = IoBuffer.allocate(comm.length(), false);
		return buf.setAutoExpand(true).putInt(comm.length())
										.put(comm.contentType())
										.put(comm.content());
	}
}
